package com.colabo.j2ee.web.core.context;

import java.io.InputStream;
import java.util.Properties;

import javax.servlet.ServletContextEvent;

import org.apache.log4j.Hierarchy;
import org.apache.log4j.Logger;
import org.apache.log4j.spi.LoggerRepository;
import org.apache.log4j.xml.DOMConfigurator;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.colabo.j2ee.web.core.exception.WrappedException;
import com.colabo.j2ee.web.core.license.ILicense;
import com.colabo.j2ee.web.core.license.LicenseFactory;
import com.colabo.j2ee.web.core.log.DaemonLogger;
import com.colabo.j2ee.web.core.log.LogManager;
import com.colabo.j2ee.web.core.util.PropertyUtil;


/**
 * Invoke by listener defined in <code>web.xml</code> to start the core framework. 
 * Note: datasource access is not initiated yet here.
 * @author Anthony Do
 *	@since 2009-12-23
 */

public class CoreInit {
	
	private static boolean CORE_INITED = false;
	private static String LOG_CONFIG_FILE_PATH = "/WEB-INF/classes/config/log/log4j_config.xml";
	private static String MSG_FILE_DIRECTORY = "config.msg";
	private static String DEFAULT_ERROR_PAGE = "/unknownException.jsp";
	private static boolean PROGRAMMATICALLY_SET_LOG = true;
	

	/**
	 * do the init process
	 * @param context
	 * 			java servlet context
	 */
	public static synchronized void init(ServletContextEvent context) {	
		ILicense license = LicenseFactory.getInstance().getLicense();
		try {
			if (license.isValid()) {
			ApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(context
					.getServletContext());
			ContextUtil.setApplicationContext(ctx);
			}
		} catch (IllegalStateException e) {
			DaemonLogger.logError(e);
		} catch (WrappedException e) {
			DaemonLogger.logError(e.getStackTraceString());
		}
		
		if (CORE_INITED) {
			return;
		}
		
		// retrieve system configuration from properties file in "SYSTEM_CONFIGS"
		Properties configs = PropertyUtil.init(CoreInitInfo.SYSTEM_CONFIGS);
		CoreInitInfo.getInstance().setSystemConfigs(configs);
		
		/**
		 * if you set the config in web.xml, u dont need this
		 */
		if (PROGRAMMATICALLY_SET_LOG) {
			if (context != null) {
				initLog(context, configs);
			} else {
				initLog();
			}
		}
		
		// load system config
		initSystemConfig();
		
		// retrieve application messages or I18N resources
		initMsgFilePath();

		// retrieve the default error page
		initErrorPage();
		
		CORE_INITED = true;
	}
	
	private static void initErrorPage() {
		CoreInitInfo.getInstance().setDefaultErrorPageURL(DEFAULT_ERROR_PAGE);
	}

	private static void initMsgFilePath() {
		CoreInitInfo.getInstance().setMsgFileDirectory(MSG_FILE_DIRECTORY);
	}
	
	private static void initLog() {
		LogManager.init(LOG_CONFIG_FILE_PATH);
	}
	
	private static void initSystemConfig() {
		Properties props = PropertyUtil.init(CoreInitInfo.SYSTEM_CONFIGS);
		CoreInitInfo.getInstance().setSystemConfigs(props);
	}

	private static void initLog(ServletContextEvent context, Properties props) {
		InputStream is = null;
		try {
			is = context.getServletContext().getResourceAsStream(LOG_CONFIG_FILE_PATH);
			LoggerRepository h = new Hierarchy(Logger.getRootLogger());
			DOMConfigurator domc = new DOMConfigurator();
			domc.doConfigure(is, h);
		} catch (Exception e) {
			DaemonLogger.logError(e);
			// load the log4j config failed, then load the default config
			initLog();
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (Exception e) {
					DaemonLogger.logError(e);
				}
			}
		}
	}
	
	/**
	 * destroy
	 */
	public static void destroy() {
		CORE_INITED = false;
	}
}
